package org.yierge.crm.ssm.plus.account.service.impl;

import com.alibaba.fastjson.JSON;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.stereotype.Service;
import org.yierge.crm.ssm.plus.account.pojo.param.UserLoginInfoParam;
import org.yierge.crm.ssm.plus.account.pojo.vo.UserLoginResultVO;
import org.yierge.crm.ssm.plus.account.security.CustomUserDetails;
import org.yierge.crm.ssm.plus.account.service.UserService;

import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Slf4j
@Service(value = "account_userServiceImpl")
public class UserServiceImpl implements UserService {

    @Value("${crm.jwt.secret-key}")
    private String secretKey;
    @Value("${crm.jwt.duration-in-minute}")
    private long durationInMinute;
    @Autowired
    private AuthenticationManager authenticationManager;
    @Override
    public UserLoginResultVO login(UserLoginInfoParam userLoginInfoParam) {
        log.debug("开始处理【用户登录】的业务，参数：{}", userLoginInfoParam);
        Authentication authentication = new UsernamePasswordAuthenticationToken(
                userLoginInfoParam.getUsername(), userLoginInfoParam.getPassword());
        log.debug("准备调用AuthenticationManager的认证方法，判断此用户名、密码是否可以成功登录……");
        Authentication authenticateResult = authenticationManager.authenticate(authentication);
        log.debug("验证用户登录成功，返回的认证结果：{}", authenticateResult);

        Object principal = authenticateResult.getPrincipal();
        log.debug("从认证结果中获取当事人：{}", principal);
        CustomUserDetails userDetails = (CustomUserDetails) principal;
        Long id = userDetails.getId();
        log.debug("从认证结果中的当事人中获取ID：{}", id);
        String username = userDetails.getUsername();
        log.debug("从认证结果中的当事人中获取用户名：{}", username);
        String avatar = userDetails.getAvatar();
        log.debug("从认证结果中的当事人中获取头像：{}", avatar);
        Collection<? extends GrantedAuthority> authorities = userDetails.getAuthorities();
        log.debug("从认证结果中的当事人中获取权限列表：{}", authorities);
        String authoritiesJsonString = JSON.toJSONString(authorities);
        log.debug("将权限列表对象转换为JSON格式的字符串：{}", authoritiesJsonString);

        Date date = new Date(System.currentTimeMillis() + 1L * 60 * 1000 * durationInMinute);
        //                                                 ↑ 注意加L，避免int溢出为负数
        Map<String, Object> claims = new HashMap<>();
        claims.put("id", id);
        claims.put("username", username);
        claims.put("authoritiesJsonString", authoritiesJsonString);
        String jwt = Jwts.builder()
                .setHeaderParam("alg", "HS256")
                .setHeaderParam("typ", "JWT")
                .setClaims(claims)
                .setExpiration(date)
                .signWith(SignatureAlgorithm.HS256, secretKey)
                .compact();

        UserLoginResultVO userLoginResultVO = new UserLoginResultVO()
                .setId(id)
                .setUsername(username)
                .setAvatar(avatar)
                .setToken(jwt);
        return userLoginResultVO;
        // 改为使用JWT后，不必在登录成功后就将认证信息存入到SecurityContext中
        // log.debug("准备将认证信息结果存入到SecurityContext中……");
        // SecurityContext securityContext = SecurityContextHolder.getContext();
        // securityContext.setAuthentication(authenticateResult);
        // log.debug("已经将认证信息存入到SecurityContext中，登录业务处理完成！");
    }
}
